import java.awt.Color;
import java.awt.Dimension;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.text.NumberFormat;
import java.util.ArrayList;
import java.util.Collections;

import javax.swing.*;
import javax.swing.border.Border;


public class MainFrame extends JFrame implements ActionListener {
	/**
	 * 
	 */
	private static final long serialVersionUID = 1L;
	public static final int HEIGHT = 650;
	public static final int WIDTH = 580;
	private Border krawedz = BorderFactory.createLineBorder(Color.black);

	JPanel menu, screen, m1, m2, zad;
	JButton bAddTask, bPrintChart, bRandom, bClear;
	JTextField[] cTimeFields, periodFields;
	JTextField rangeMax, rangeMin;
	JLabel[] zadaniaL;
	JLabel cmaxL, scheduleL, scheduleLN;
	int tasksIndex, a[], b[];
	String dane1 = "";
	String dane2 = "";
	int okresy[];
	int RMSTable[];
	ArrayList<Integer>[] Tasks;
	ArrayList<Integer> tasksIndexyOkres; // indeksy priorytetÄ‚Å‚w
	ArrayList<String> zadania=new ArrayList<String>();
	
	
	public MainFrame() {
		super("Algorytm RMS - Wojciech Śliwa, Grzegorz Sendra");
		

		cTimeFields = new JTextField[20];
		periodFields = new JTextField[20];
		zadaniaL = new JLabel[20];
		tasksIndex = 0;

		menu = new JPanel();
		menu.setBackground(new Color(180, 208, 228));
		menu.setPreferredSize(new Dimension(150, 600));
		menu.setBorder(krawedz);

		bAddTask = new JButton("Dodaj zadanie");
		bAddTask.setPreferredSize(new Dimension(140, 50));
		bAddTask.addActionListener(this);

		bRandom = new JButton("Losowe wartości");
		bRandom.setPreferredSize(new Dimension(140, 50));
		bRandom.addActionListener(this);

		JPanel temp = new JPanel();
		temp.setBackground(new Color(180, 208, 228));
		JLabel rangeLMin = new JLabel("Okres od:");
		rangeMin = new JTextField("10");
		rangeMin.setPreferredSize(new Dimension(25, 20));

		JLabel rangeLMax = new JLabel("do:");
		rangeMax = new JTextField("20");
		rangeMax.setPreferredSize(new Dimension(25, 20));

		temp.add(rangeLMin);
		temp.add(rangeMin);

		temp.add(rangeLMax);
		temp.add(rangeMax);

		bClear = new JButton("Wyczyść");
		bClear.setPreferredSize(new Dimension(140, 50));
		bClear.addActionListener(this);

		bPrintChart = new JButton("Generuj wykres");
		bPrintChart.setPreferredSize(new Dimension(140, 50));
		bPrintChart.addActionListener(this);

		cmaxL = new JLabel();
		scheduleL = new JLabel();
		scheduleLN = new JLabel();

		menu.add(bAddTask);
		menu.add(bRandom);
		menu.add(temp);
		menu.add(bClear);
		menu.add(bPrintChart);
		menu.add(cmaxL);
		menu.add(scheduleL);
		menu.add(scheduleLN);

		screen = new JPanel();
		screen.setBackground(new Color(217, 231, 241));
		screen.setPreferredSize(new Dimension(400, 600));
		screen.setLayout(new GridLayout(1, 2, 10, 10));

		zad = new JPanel();
		zad.setLocation(0, 0);
		zad.setBackground(new Color(198, 219, 234));
		zad.setPreferredSize(new Dimension(60, 575));
		zad.setBorder(krawedz);
		zad.setLayout(new GridLayout(21, 1, 10, 10));

		JLabel zad1 = new JLabel("Zadania");
		zad.add(zad1);
		for (int i = 0; i < 20; i++) {
			zadaniaL[i] = new JLabel("Zadanie " + (i + 1));
			zad.add(zadaniaL[i]);
			zadaniaL[i].setVisible(false);
		}

		screen.add(zad);

		m1 = new JPanel();
		m1.setLocation(0, 0);
		m1.setBackground(new Color(217, 231, 241));
		m1.setPreferredSize(new Dimension(50, 575));
		m1.setBorder(krawedz);
		m1.setLayout(new GridLayout(21, 1, 10, 10));

		JLabel lm1 = new JLabel("Czas Trwania");
		m1.add(lm1);
		for (int i = 0; i < 20; i++) {
			cTimeFields[i] = new JTextField();
			m1.add(cTimeFields[i]);
			cTimeFields[i].setVisible(false);
		}

		screen.add(m1);

		m2 = new JPanel();
		m2.setBackground(new Color(217, 231, 241));
		m2.setPreferredSize(new Dimension(50, 575));
		m2.setBorder(krawedz);
		m2.setLayout(new GridLayout(21, 1, 10, 10));

		JLabel lm2 = new JLabel("Okres");
		m2.add(lm2);
		for (int i = 0; i < 20; i++) {
			periodFields[i] = new JTextField();
			m2.add(periodFields[i]);
			periodFields[i].setVisible(false);
		}

		screen.add(m2);

		add(menu);

		add(screen);
		setVisible(true);
	}

	/**
	 * Wstaw losowe wartosci
	 */
	@Override
	public void actionPerformed(ActionEvent e) {
		Object source = e.getSource();
		if (source == bAddTask) {
			System.out.println("dodaj task");
			cTimeFields[tasksIndex].setVisible(true);
			periodFields[tasksIndex].setVisible(true);
			zadaniaL[tasksIndex].setVisible(true);
			tasksIndex++;

		} else if (source == bRandom) {
			System.out.println("random");
			for (int i = 0; i < tasksIndex; i++) {
				cTimeFields[i]
						.setText(""
								+ ((int) Math.round(Math.random()
										* (Integer.parseInt(rangeMax.getText()) - Integer
												.parseInt(rangeMin.getText()))
										+ Integer.parseInt(rangeMin.getText())))
								/ 5);
				periodFields[i]
						
						.setText(""
								+ (int) Math.round(Math.random()
										* (Integer.parseInt(rangeMax.getText()) - Integer
												.parseInt(rangeMin.getText()))
										+ Integer.parseInt(rangeMin.getText())));
			}

		} else if (source == bPrintChart) {
			System.out.println("rysuj");
			if (isPossible() == true) {
				RMS();
				new Chart("Wykres RMS", Tasks,
						tasksIndex, dane1, dane2,zadania);
			} else {
				dane1 = "";
				dane2 = "";
			}

		} else if (source == bClear) {
			for (int i = 0; i < tasksIndex; i++) {
				cTimeFields[i].setVisible(false);
				periodFields[i].setVisible(false);
				cTimeFields[i].setText("");
				periodFields[i].setText("");
				zadaniaL[i].setVisible(false);
			}
			tasksIndex = 0;
		}

	}
	
	/**
	 * Sprawdza czy mozliwe jest uszeregowanie
	 * @return
	 */
	public boolean isPossible() {
		double suma = 0;
		int ilosc = tasksIndex;
		dane1 += "Całkowite obciążenie procesora\n";
		for (int i = 0; i < tasksIndex; i++) {
			double obciazenie = (double) Integer.parseInt(cTimeFields[i]
					.getText())
					/ (double) Integer.parseInt(periodFields[i].getText());
			suma += obciazenie;
			dane1 += "Zadanie" + (i + 1) + ": " + obciazenie * 100 + "%\n";
		}
		dane1 += "\nŁączne obciążenie procesora: " + suma * 100 + "%\n\n";
		if (suma <= ilosc * ((Math.pow(2, 1 / (double) ilosc)) - 1)) {
			
			return true;
		}
		suma=suma*100;
		NumberFormat nf = NumberFormat.getInstance();
	    nf.setMaximumFractionDigits(0);
	    String round = nf.format(suma);
		JOptionPane.showMessageDialog(null, "Warunki zadania nie zostaly spelnione, " +
				"ponieważ zostało przekroczone \noptymalne wykorzystanie procesora(około 70%) i wynosi ono:"
				+ round + "%","Błąd!",JOptionPane.ERROR_MESSAGE);

		return false;
	}
	/**
	 * Wykonanie algorytmu RMS
	 */
	public void RMS() {
		int NWW = NWW_start();
		dane2 += "Okres wykonania wszystkich zadań: " + NWW + "\n\n";
		RMSTable = new int[NWW];
		tasksIndexyOkres = new ArrayList<>();
		okresy = new int[tasksIndex];
		for (int i = 0; i < tasksIndex; i++) {
			okresy[i] = Integer.parseInt(periodFields[i].getText());
		}

		for (int i = 0; i < tasksIndex; i++) {
			int min = 1000;
			int index = -1;
			for (int j = 0; j < tasksIndex; j++) {
				if (okresy[j] < min) {
					min = index = j;
				}
			}
			okresy[index] = 1000;
			tasksIndexyOkres.add(index);
		}
		Tasks = new ArrayList[tasksIndex];
		dane2 += "Ilość zadań: " + tasksIndex + "\n";
		
	
	
		ArrayList<Tasks> lista = new ArrayList<Tasks>();
		String name="";
		for(int i=0;i<tasksIndex;i++){
			int temp=i+1;
			name="Zadanie "+temp;
			lista.add(new Tasks(name,Integer.parseInt(cTimeFields[tasksIndexyOkres.get(i)]
					.getText()), Integer.parseInt(periodFields[tasksIndexyOkres.get(i)]
					.getText())));
		}
		Collections.sort(lista);
		
		for(int i=0;i<lista.size();i++){
			zadania.add(lista.get(i).getName());
		}

		
		for (int i = 0; i < tasksIndex; i++) {
			Tasks[i] = new ArrayList<Integer>();

			//int ctime = Integer.parseInt(cTimeFields[tasksIndexyOkres.get(i)]
					//.getText());
			
			int ctime = lista.get(i).getCtime();
			
			//int okres = Integer.parseInt(periodFields[tasksIndexyOkres.get(i)]
					//.getText());
			int okres = lista.get(i).getPeriod();
			
			dane2 += lista.get(i).getName() + " - Czas trwania: " + ctime + " - Okres: "
					+ okres + " - Priorytet: " + (i + 1) + "\n";
			for (int r = 0; r < NWW / okres; r++) {
				int end = okres * r + okres - 1;
				int ilosc = ctime;
				for (int s = okres * r; s <= end; s++) {
					if (RMSTable[s] == 0 && ilosc > 0) {
						RMSTable[s] = 1;
						ilosc--;
						Tasks[i].add(s);
					}
				}
			}
		}

	}

	public int NWW_start() {
		int a = Integer.parseInt(periodFields[0].getText());
		int temp;
		int ilosc = tasksIndex;
		if (ilosc == 1) {
			return a;
		} else {
			temp = a;
			for (int i = 1; i < ilosc; i++) {
				temp = NWW(temp, Integer.parseInt(periodFields[i].getText()));
			}
			return temp;
		}
	}
	/**
	 * Okres wykonania wszystkich zadan - NWW
	 * @param a
	 * @param b
	 * @return
	 */
	public int NWW(int a, int b) {
		int t;
		int ab = a * b;
		while (b != 0) {
			t = b;
			b = a % b;
			a = t;
		}
		ab /= a;
		return ab;
	}
}
